/*
	此代码将128位的数据接收后，再依次将这128为数据分为16个8位的数据输出
	(先发送高8位数据)
*/
module serial_port_many_output
#(	parameter data_in_bits = 40,		//数据位宽定义
	parameter cnt_txdata_tybe_bits = 4	//字节个数对应的计数器的位宽
	
)(
		clk,
		rst_n,
		serial_port_en,
		baud_set,
		user_read_data,
		
		rs232_tx,
		tx_data_suecess,//一组多字节发送结束
		tx_done,//一个字节发送结束
		uart_state
);
		input clk				;
		input rst_n				;
		input serial_port_en	;	//数据发送使能
		// input data_en			;//数据发送使能
		input [2:0]baud_set		;//波特率设置
		input [data_in_bits - 1:0] user_read_data	;
      // input [7:0]data_byte	;//输入的数据
		
		output rs232_tx		;//输出的数据
		output tx_data_suecess;
		output tx_done			;//输出结束信号
		output uart_state		;//输出状态
		
		reg [7:0]data_byte;
		reg data_en;
		//按下信号处理
		reg send_en;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				send_en<=1'b0;
			else if(data_en)
						send_en<=1'b1;
					else 
						send_en<=1'b0;
		
		
		//波特率分频技术最大值
		reg [15:0]bps_dr;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				bps_dr<=16'd5207;
		else begin 
				case(baud_set)
					0:bps_dr<=16'd5207;	//9600bps
					1:bps_dr<=16'd2603;	//19200bps
					2:bps_dr<=16'd1301;	//38400bps
					3:bps_dr<=16'd867;	//57600bps
					4:bps_dr<=16'd433;	//115200bps
					default:bps_dr<=16'd5207;
				endcase
				end
		
		
		//分频时钟计数
		reg [15:0]div_cnt;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				div_cnt<=16'd0;
			else if(uart_state)
						if(div_cnt==bps_dr)
							div_cnt<=16'd0;
						else 
							div_cnt<=div_cnt+1'b1;
					else 
						div_cnt<=16'd0;
		
		
		//波特率时钟
		reg bps_clk;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				bps_clk<=0;
			else if(div_cnt==16'd1)
						bps_clk<=1'b1;
					else 
						bps_clk<=0;
			
			
		//波特率时钟计数器
		reg [3:0]bps_cnt;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				bps_cnt<=4'd0;
			else if(bps_cnt==4'd11)
						bps_cnt<=4'd0;
					else if(bps_clk)
								bps_cnt<=bps_cnt+1'b1;
							else 
								bps_cnt<=bps_cnt;
								
		
		
		//数据输出结束信号
		reg tx_done;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				tx_done<=1'b0;
			else if(bps_cnt==4'd11)
						tx_done<=1'b1;
					else 
						tx_done<=1'b0;
					
			
		//数据输出状态设置
		reg uart_state;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				uart_state<=1'b0;
			else if(send_en)
						uart_state<=1'b1;
					else if(bps_cnt==4'd11)
								uart_state<=1'b0;
							else 
								uart_state<=uart_state;
						
					
		//数据寄存（保证数据稳定）
		reg [7:0]r_data_byte;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				r_data_byte<=8'd0;
			else if(send_en)
						r_data_byte<=data_byte;
					else 
						r_data_byte<=r_data_byte;
						
		
		//数据输出设置  //先出低位 后出高位
		localparam start_bit=1'b0;
		localparam stop_bit=1'b1;
		reg rs232_tx;
		always@(posedge clk or negedge rst_n)
			if(!rst_n)
				rs232_tx<=1'b0;
			else begin
					case(bps_cnt)
							0:rs232_tx<=1'b1;
							1:rs232_tx<=start_bit;
							2:rs232_tx<=r_data_byte[0];
							3:rs232_tx<=r_data_byte[1];
							4:rs232_tx<=r_data_byte[2];
							5:rs232_tx<=r_data_byte[3];
							6:rs232_tx<=r_data_byte[4];
							7:rs232_tx<=r_data_byte[5];
							8:rs232_tx<=r_data_byte[6];
							9:rs232_tx<=r_data_byte[7];
						  10:rs232_tx<=stop_bit;
							default:rs232_tx<=1'b1;
					endcase	
			end

		
	//串口数据128位转为8位数据输出
	wire [data_in_bits - 1:0] user_read_data;
	reg [data_in_bits - 1:0] user_read_data_reg;
	reg [cnt_txdata_tybe_bits - 1:0]cnt_txdata_tybe;
	reg tx_data_suecess;
	reg [1:0]state_fifo_read;
	localparam
		state_idle=2'd0,
		state_read_judge=2'd1,
		state_read_conduct=2'd2;
		always@(posedge clk or negedge rst_n)
		if(!rst_n) begin
			cnt_txdata_tybe <= {cnt_txdata_tybe_bits{1'b0}};
			data_en <= 1'b0;
			data_byte <= 8'd0;
			tx_data_suecess <= 1'b0;
			user_read_data_reg <= {data_in_bits{1'b0}};//
			state_fifo_read <= state_idle;
		end
		else begin
			case(state_fifo_read)
				state_idle:begin
					cnt_txdata_tybe <= {cnt_txdata_tybe_bits{1'b0}};
					data_en <= 1'b0;
					data_byte <= 8'd0;
					tx_data_suecess <= 1'b0;
					state_fifo_read <= state_read_judge;
				end
				
				state_read_judge:begin
					if(serial_port_en == 1'b1) begin
						cnt_txdata_tybe <= {cnt_txdata_tybe_bits{1'b0}};
						data_en <= 1'b1;
						tx_data_suecess <= 1'b0;
						data_byte <= user_read_data[data_in_bits - 1:data_in_bits - 8];
						user_read_data_reg <= {user_read_data[data_in_bits - 9:0],user_read_data[data_in_bits - 1:data_in_bits - 8]};//
						state_fifo_read <= state_read_conduct;
					end
					else begin
						cnt_txdata_tybe <= {cnt_txdata_tybe_bits{1'b0}};
						data_en <= 1'b0;
						data_byte <= 8'd0;
						tx_data_suecess <= 1'b0;
						state_fifo_read <= state_fifo_read;
					end	
				end
				
				state_read_conduct: begin
					if(tx_done==1'b1) begin
						data_byte <= user_read_data_reg[data_in_bits - 1:data_in_bits - 8];//
						user_read_data_reg <= {user_read_data_reg[data_in_bits - 9:0],user_read_data_reg[data_in_bits - 1:data_in_bits - 8]};//
						if(cnt_txdata_tybe==data_in_bits/8 -1) begin
							cnt_txdata_tybe <= {cnt_txdata_tybe_bits{1'b0}};
							data_en <= 1'b0;
							tx_data_suecess <= 1'b1;
							state_fifo_read <= state_idle;
						end
						else begin
							data_en <= 1'b1;
							cnt_txdata_tybe <= cnt_txdata_tybe + 1'b1;
						end 
					end
					else begin
						data_byte <= data_byte;
						data_en <= 1'b0;
						tx_data_suecess <= 1'b0;
						state_fifo_read <= state_fifo_read;
					end
						
				end
				
				default:state_fifo_read <= state_idle;
			endcase
		end
		
endmodule 